package uk.me.dewi.appenin.android.dao.rest;

import java.util.ArrayList;
import java.util.Date;

import uk.me.dewi.appenin.android.dao.PlaceDao;
import uk.me.dewi.appenin.android.entity.Place;
import uk.me.dewi.net.rest.RestClient;
import uk.me.dewi.net.rest.RestException;

import com.google.android.maps.GeoPoint;

public abstract class PlaceRestDao implements PlaceDao {

    protected RestClient mRestClient;
    
    public PlaceRestDao(AppeninHttpRequestFactory requestFactory){
        this.mRestClient = new RestClient(requestFactory);
    }

    /* (non-Javadoc)
     * @see uk.me.dewi.appenin.android.AppeninRestAdapter#createPlace(java.lang.String, java.lang.String)
     */
    public Place createPlace(Place place) throws RestException {
        return createPlace("/places/", place);
    }

    /* (non-Javadoc)
     * @see uk.me.dewi.appenin.android.AppeninRestAdapter#deletePlace(long)
     */
    public boolean deletePlace(long id) throws RestException {
        return deletePlace("/places/"+id);
    }

    /* (non-Javadoc)
     * @see uk.me.dewi.appenin.android.AppeninRestAdapter#getNearbyPlaces(com.google.android.maps.GeoPoint, int)
     */
    public ArrayList<Place> getNearbyPlaces(GeoPoint location, int distance) throws RestException {
        return getNearbyPlaces(buildGeoPath(location, distance));
    }
    
    /* (non-Javadoc)
     * @see uk.me.dewi.appenin.android.AppeninRestAdapter#getNearbyPlaceIDs(com.google.android.maps.GeoPoint, int)
     */
    public long[] getNearbyPlaceIDs(GeoPoint location, int distance) throws RestException {
        return getNearbyPlaceIDs(buildGeoPath(location, distance));
    }
    
    private String buildGeoPath(GeoPoint location, int distance) {
        return new StringBuilder("/places/search/")
                          .append(location.getLatitudeE6()).append("/")
                          .append(location.getLongitudeE6()).append("/")
                          .append(distance)
                          .toString();
    }
    
    /* (non-Javadoc)
     * @see uk.me.dewi.appenin.android.AppeninRestAdapter#fetchPlace(long)
     */
    public Place fetchPlace(long id) throws RestException {
        return fetchPlace("/places/"+id);
    }
    
    /* (non-Javadoc)
     * @see uk.me.dewi.appenin.android.AppeninRestAdapter#updatePlace(uk.me.dewi.appenin.android.entity.Place)
     */
    public boolean updatePlace(Place place) throws RestException {
        place.mModified = new Date();
        return updatePlace("/places/", place);
    }

    protected abstract Place createPlace(String path, Place place) throws RestException;

    protected abstract boolean deletePlace(String path) throws RestException;

    protected abstract ArrayList<Place> getNearbyPlaces(String path) throws RestException;
    
    protected abstract long[] getNearbyPlaceIDs(String path) throws RestException;
    
    protected abstract Place fetchPlace(String path) throws RestException;

    protected abstract boolean updatePlace(String path, Place place) throws RestException;
    
    public GeoPoint parseGeoString(String geoStr) {
        try{
            int commaPos = geoStr.indexOf(',');

            Double latitudeE6 = Double.parseDouble(geoStr.substring(0, commaPos)) *1E6;
            Double longitudeE6 = Double.parseDouble(geoStr.substring(commaPos+1)) *1E6;

            return new GeoPoint(latitudeE6.intValue(),longitudeE6.intValue());
        }catch(Exception e){
            throw new RuntimeException("Could not parse GeoPoint: "+geoStr, e);
        }
    }
}
